#include <iostream> 
#include <vector>
#include <cstring>
#include <limits>
 
using std::cout;
using std::endl;
using std::cin;
using std::istream;
using std::ostream;
using std::vector;

// 自定义一个String类保存字符串内容，
// 实现以下String类的各个函数，
// 并给出相应的测试用例

class String 
{
friend bool operator==(const String& lhs, const String& rhs);
friend bool operator!=(const String& lhs, const String& rhs);

friend bool operator<(const String& lhs, const String& rhs);
friend bool operator>(const String& lhs, const String& rhs);
friend bool operator<=(const String& lhs, const String& rhs);
friend bool operator>=(const String& lhs, const String& rhs);

friend ostream& operator<<(ostream& os, const String& s);
friend istream& operator>>(istream& is, String& s);

friend String operator+(const String& lhs, const String& rhs);
friend String operator+(const String& lhs, const char* rhs);
friend String operator+(const char* lhs, const String& rhs);

public:
	String();
	String(const char* str);
	String(const String& str);

	~String();

	String& operator=(const String& rhs);
	String& operator=(const char* rhs);

	String& operator+=(const String& rhs);
	String& operator+=(const char* rhs);
	
	char& operator[](std::size_t index);
	const char& operator[](std::size_t index) const;
	
	std::size_t size() const;
	const char* c_str() const;

private:
	char * _pstr;
    size_t _size;
};


String::String()
    : _pstr(new char[1] ())
    , _size(0){}
String::String(const char* str)
    : _pstr(new char[strlen(str) + 1] ())
    , _size(strlen(str)){
    strcpy(_pstr, str);
}
String::String(const String& str)
    : _pstr(new char[str._size + 1] ())
    , _size(str._size){
    strcpy(_pstr, str._pstr);
}


String::~String(){
    if(_pstr){
        delete [] _pstr;
        _pstr = nullptr;
    }
}


String& String::operator=(const String& rhs){
    delete [] _pstr;
    new char[rhs._size + 1] ();
    strcpy(_pstr, rhs._pstr);
    _size = rhs._size;
    return *this;
}
String& String::operator=(const char* rhs){
    delete [] _pstr;
    new char[strlen(rhs) + 1] ();
    strcpy(_pstr, rhs);
    _size = strlen(rhs);
    return *this;
}


String& String::operator+=(const String &rhs){
    char* temp = new char[_size + rhs._size + 1] ();
    strcat(temp, _pstr);
    strcat(temp, rhs._pstr);
    delete [] _pstr;
    _pstr = temp;
    _size = strlen(temp);
    return *this;
}
String& String::operator+=(const char *rhs){
    char* temp = new char[_size + strlen(rhs) + 1] ();
    strcat(temp, _pstr);
    strcat(temp, rhs);
    delete [] _pstr;
    _pstr = temp;
    _size = strlen(temp);
    return *this;  
}


char& String::operator[](std::size_t index){
    if(index >= _size){throw "访问越界";}
    return _pstr[index];
}
const char& String::operator[](std::size_t index) const{
    if(index >= _size){throw "访问越界";}
    return _pstr[index];
}


size_t String::size() const{
    return _size;
}
const char* String::c_str() const{
    return _pstr;
}


bool operator==(const String& lhs, const String& rhs){
    return !strcmp(lhs._pstr, rhs._pstr);
}
bool operator!=(const String& lhs, const String& rhs){
    return strcmp(lhs._pstr, rhs._pstr);
}
bool operator<(const String& lhs, const String& rhs){
    return strcmp(lhs._pstr, rhs._pstr) < 0;
}
bool operator>(const String& lhs, const String& rhs){
    return strcmp(lhs._pstr, rhs._pstr) > 0;
}
bool operator<=(const String& lhs, const String& rhs){
    return strcmp(lhs._pstr, rhs._pstr) <= 0;
}
bool operator>=(const String& lhs, const String& rhs){
    return strcmp(lhs._pstr, rhs._pstr) >= 0;
}


ostream& operator<<(ostream& os, const String& rhs){
    os << rhs._pstr;
    return os;
}
istream& operator>>(istream& is, String& rhs){
    vector<char> v;
    v.reserve(128);
    char ch;
    is >> ch;
    v.push_back(ch);
    while(is.get(ch)){
        if(ch == ' ' || ch == '\n'){
            is.unget();
            break;
        }
        v.push_back(ch);
    }

    delete [] rhs._pstr;
    rhs._pstr = new char[v.size() + 1] ();
    rhs._size = v.size();
    for(size_t i = 0; i < v.size(); ++i){
        rhs[i] = v[i]; 
    }
    return is;

}


String operator+(const String& lhs, const String& rhs){
    char* temp  = new char[strlen(lhs._pstr) + strlen(rhs._pstr) + 1] ();
    strcat(temp, lhs._pstr);
    strcat(temp, rhs._pstr);
    String s(temp);
    delete [] temp;
    return s;
}
String operator+(const String& lhs, const char* rhs){
    char* temp  = new char[strlen(lhs._pstr) + strlen(rhs) + 1] ();
    strcat(temp, lhs._pstr);
    strcat(temp, rhs);
    String s(temp);
    delete [] temp;
    return s;
}
String operator+(const char* lhs, const String& rhs){
    char* temp  = new char[strlen(lhs) + strlen(rhs._pstr) + 1] ();
    strcat(temp, lhs);
    strcat(temp, rhs._pstr);
    String s(temp);
    delete [] temp;
    return s;
}


int main(void)
{
    String S1("huzhu");
    
    String S2("the best");
    cout << "@@@ " + S1 + " " + S2 << endl;
    cout << "S1.size() = " << S1.size() << endl;
    cout << "S2.size() = " << S2.size() << endl;

    cout << (S1 == S2) << endl;
    cout << (S1 != S2) << endl;
    cout << (S1 < S2) << endl;
    cout << (S1 > S2) << endl;
    cout << (S1 <= S2) << endl;
    cout << (S1 >= S2) << endl;

    cout <<"S1[2] = " << S1[2] << endl;
    S1[0] = 'H';

    
    String S3 = S1 + " is " + S2 + " boy.";
    cout << S3 << endl;

    String S4;
    cin >> S4;
    cout << S4 << endl;

    return 0;
}